/*global FBL */
FBL.ns(function () {
	with (FBL) {
		var panelName = "ojscfirebug";		
		
		Firebug.OJSCModel = extend(Firebug.Module, {
		    showPanel: function(browser, panel) {
				var isPanel = panel && panel.name === panelName;
				var ojcsButtons = browser.chrome.$("fbOJSCButtons");
				collapse(ojcsButtons, !isPanel);
		    },
		
			addStyleSheet : function (doc) {
				var styleSheet = document.getElementById("ojsc-firebug-style");
				if (!styleSheet) {
					styleSheet = createStyleSheet(doc, "chrome://ojscfirebug/skin/ojsc-firebug.css");
					styleSheet.id = "ojsc-firebug-style";
					addStyleSheet(doc, styleSheet);
				}
			},

		   	onActivate: function(context) {
				var browser = FirebugChrome.getCurrentBrowser();
				browser.chrome.selectPanel(panelName);
				
		        var panel = context.getPanel(panelName);
			    var parentNode = panel.panelNode;
			    var results = ojscfirebug.run();
				var runButton = document.getElementById("ojcsButton");
				if (results && results.events) {
					Firebug.toggleBar(true, panelName);
					runButton.label = "Hide OJSC";
					runButton.setAttribute("tooltiptext", "Hide Obtrusive JavaScript Checker");
					
					var inlineEvents = "<table cellspacing='0'>";
					for (eventHandler in results.events) {
						if (eventHandler !== "items") {
							inlineEvents += "<tr><th colspan='2'>" + eventHandler + ":</th><td>" + results.events[eventHandler] + "</td></tr>";
						}
					}
					inlineEvents += "</table>";
					var ojcsReport = domplate({
						reportListing:
						DIV({class: "ojsc-result-container"},
								TABLE(
									{cellspacing: 0},
									TR(
										{class: "label"},
										TH(
											{},
											"javascript: links:"
										),
										TD(
											{},
											results.links.items
										)
									),
									TR(
										{class: "label"},
										TH(
											{},
											"Inline events:"
										),
										TD(
											{},
											results.events.items
										)
									)
								),
								DIV(
									{class: "event-types-container"}, 
									inlineEvents
								)
					        )
					});

					var rootTemplateElement = ojcsReport.reportListing.replace({}, parentNode, ojcsReport);
				}
				else {
					runButton.label = "Run OJSC";
					runButton.setAttribute("tooltiptext", "Run Obtrusive JavaScript Checker");
					Firebug.toggleBar(false, panelName);
				}
		    }
		});
			
		
		function OJSCPanel () {
			
		}
		OJSCPanel.prototype = extend(Firebug.Panel, {
			name : panelName,
			title : "Obtrusive JavaScript Checker",
			initialize : function () {
				Firebug.Panel.initialize.apply(this, arguments);
				Firebug.OJSCModel.addStyleSheet(this.document);
				ojscfirebug.init();
			}
		});
		
		Firebug.registerModule(Firebug.OJSCModel);
		Firebug.registerPanel(OJSCPanel);
	}
});

var ojscfirebug = function () {
	var regExp = /^on/i,
		regExpLink = /^javascript:/i,
		regExpClasses = /ojscfirebug\-(inline\-event|javascript\-link)/gi,
		regExpSpaceMatch = /^\s+.*\s+$/,
		regExpSpaceReplace = /(\s+).+/,
		regExpSpaceFix = /^\s+|\s+$/g,
		classReplace = function (match) {
			var retVal = "";
			if (regExpSpaceMatch.test(match)) {
				retVal = match.replace(regExpSpaceReplace, "$1");
			}
			return retVal;
		},
		styles = [
			"position : fixed",
			"display : none",
			"min-width : 300px",
			"font : 12px Helvetica, Verdana, Arial, sans-serif",
			"color : #fff",
			"background : #333",
			"text-align: left",
			"padding : 10px",
			"z-index : 1000",
			"opacity : 0.9",
			"-moz-border-radius : 5px"
		],
		reportStyles = [
			"display : block",
			"width : 200px",
			"left : 0",
			"bottom : 0"
		],
		innerStyles = [
			"font : 12px Helvetica, Verdana, Arial, sans-serif",
			"color : #fff",
			"margin: 0 0 10px 0;"
		],
		inlineEvents = {
			items : 0
		},
		javascriptLinks = {
			items : 0
		},
		inlineEventElmStyle = [
			"border : 2px solid red"
		],		
		javascriptLinksElmStyle = [
			"border : 2px solid magenta"
		],
		states = {
			
		},
		attribute,
		attrName;
	return {
		init : function () {
			gBrowser.addEventListener("load", function () {
				ojscfirebug.clearState.apply(ojscfirebug, arguments);
			}, false);
		},
		
		getTabIndex : function () {
			var browsers = gBrowser.browsers,
				tabIndex;
			for (var i=0, il=browsers.length, browser; i<il; i++) {
				if(gBrowser.getBrowserAtIndex(i).contentWindow === content) {
					tabIndex = i;
					break;
				}
			}
			return tabIndex;
		},
		
		getState : function () {
			var tabIndex = this.getTabIndex(),
				state = states[tabIndex];
			return state;	
		},
		
		clearState : function () {
			var state = this.getState();
			this.clearAll();
			state.hasRun = false;
		},
			
		run : function () {
			var state = this.getState(),
				tabIndex = this.getTabIndex();
			if(!state) {
				state = states[tabIndex] = {
					hasRun : false,
					affectedElms : []
				};
			}
			this.clearAll();
			
			if (state.hasRun) {
				state.hasRun = false;
				return;
			}
			else {
				state.hasRun = true;
			}
			
			
			var affectedElms = state.affectedElms;
			
			// Needed to be here to make sure HTML elements are retrieved from the active tab
			var allElms = content.document.body.getElementsByTagName("*");
			
			// Creation of custom style sheet
			var styleSheet = content.document.createElement("style");
			styleSheet.id = "ojscfirebug-style";
			styleSheet.type = "text/css";
			styleSheet.rel = "stylesheet";
			styleSheet.href = "http://sites/test/test.css";
			content.document.getElementsByTagName("head")[0].appendChild(styleSheet);
			
			// Append CSS rules to it
			var docStyleSheets = content.document.styleSheets,
				lastStyleSheet = docStyleSheets.length - 1;
			docStyleSheets[lastStyleSheet].insertRule(("div.ojscfirebug-overlay {" + styles.join(";\n") + "}"), 0);
			docStyleSheets[lastStyleSheet].insertRule(("div.ojscfirebug-overlay-report {" + reportStyles.join(";\n") + "}"), 1);
			docStyleSheets[lastStyleSheet].insertRule(("div.ojscfirebug-overlay p {" + innerStyles.join(";\n") + "}"), 2);
			docStyleSheets[lastStyleSheet].insertRule((".ojscfirebug-inline-event {" + inlineEventElmStyle.join(";\n") + "}"), 3);
			docStyleSheets[lastStyleSheet].insertRule((".ojscfirebug-javascript-link {" + javascriptLinksElmStyle.join(";\n") + "}"), 4);
			
			var viewer,
				report,
				elm, 
				attributes, 
				attr,
				item,
				eventHandler;

			viewer = content.document.createElement("div");
			viewer.id = "ojscfirebug-viewer";
			viewer.className = "ojscfirebug-overlay";
			content.document.body.appendChild(viewer);
						
			for (var i=0, il=allElms.length; i<il; i++) {
				elm = allElms[i];
				if (elm.nodeType === 1) {
					attributes = elm.attributes;
					for (var j=0, jl=attributes.length; j<jl; j++) {
						attribute = attributes[j];
						attrName = attribute.name;
						if(regExp.test(attrName)){
							elm.className += ((elm.className.length > 0)? " " : "") + "ojscfirebug-inline-event";
							inlineEvents.items += 1;
							if (typeof inlineEvents[attrName] === "number") {
								inlineEvents[attrName] += 1;
							}
							else {
								inlineEvents[attrName] = 1;
							}
							elm.addEventListener("mouseover", this.showInfo, false);
							elm.addEventListener("mouseout", this.hideInfo, false);
							affectedElms.push(elm);
						}
						else if (attrName === "href" && regExpLink.test(attribute.value)) {
							javascriptLinks.items += 1;
							elm.className += ((elm.className.length > 0)? " " : "") + "ojscfirebug-javascript-link";
							elm.addEventListener("mouseover", this.showJavaScriptLinkInfo, false);
							elm.addEventListener("mouseout", this.hideInfo, false);
							affectedElms.push(elm);
						}
					}
				}
			}
			
			report = content.document.createElement("div");
			report.id = "ojscfirebug-report";
			report.className = "ojscfirebug-overlay ojscfirebug-overlay-report";
			report.innerHTML = "<p><b>Number of javascript: links:</b> " + javascriptLinks.items + "</p>";
			report.innerHTML += "<p><b>Number of inline events:</b> " + inlineEvents.items + "</p>";
			for (eventHandler in inlineEvents) {
				if (eventHandler !== "items") {
					report.innerHTML += "<p style='margin-left: 20px'>" + eventHandler + ": " + inlineEvents[eventHandler] + "</p>";
				}
			}
			return {
				links : javascriptLinks,
				events : inlineEvents
			};
			//content.document.body.appendChild(report);
		},	

		showInfo : function (evt) {
			var viewer = content.document.getElementById("ojscfirebug-viewer");
			var attributes = this.attributes,
				events = [],
				eventElm;
			for (var i=0, il=attributes.length; i<il; i++) {
				attribute = attributes[i];
				attrName = attribute.name;
				if(regExp.test(attrName)){
					events.push(attrName + ": " + attribute.value);
				}
			}
			viewer.innerHTML = "";
			for (var j=0, jl=events.length; j<jl; j++) {
				eventElm = content.document.createElement("p");
				eventElm.innerHTML = events[j];
				viewer.appendChild(eventElm);
			}
			ojscfirebug.positionAndShow(evt);
			evt.stopPropagation();
		},
		
		showJavaScriptLinkInfo : function (evt) {
			var viewer = content.document.getElementById("ojscfirebug-viewer");
			viewer.innerHTML = "";
			var eventElm = content.document.createElement("p");
			eventElm.innerHTML = "href: " + this.getAttribute("href");
			viewer.appendChild(eventElm);
			ojscfirebug.positionAndShow(evt);
			evt.stopPropagation();
		},
		
		positionAndShow : function (evt) {
			var viewer = content.document.getElementById("ojscfirebug-viewer");
			viewer.style.left = (evt.clientX + 10 + window.pageXOffset) + "px";	
			viewer.style.top = (evt.clientY + 10 + window.pageYOffset) + "px";
			viewer.style.display = "block";
		},
		
		hideInfo : function () {
			var viewer = content.document.getElementById("ojscfirebug-viewer");
			if (viewer) {
				viewer.style.display = "none";
			}
		},
		
		clear : function () {
			var styles = content.document.getElementById("ojscfirebug-style");
			if (styles) {
				styles.parentNode.removeChild(styles);
			}
			var viewer = content.document.getElementById("ojscfirebug-viewer");
			if (viewer && viewer.parentNode) {
				viewer.parentNode.removeChild(viewer);
			}
			var report = content.document.getElementById("ojscfirebug-report");
			if (report && report.parentNode) {
				report.parentNode.removeChild(report);
			}
			inlineEvents = {
				items : 0
			};
			javascriptLinks = {
				items : 0
			};
		},
		
		clearAll : function () {
			var state = this.getState(),
				affectedElms = state.affectedElms;
			this.clear();
			for (var i=0, il=affectedElms.length, elm; i<il; i++) {
				elm = affectedElms[i];
				elm.className = elm.className.replace(regExpClasses, classReplace).replace(regExpSpaceFix, "");
				elm.removeEventListener("mouseover", this.showInfo, false);
				elm.removeEventListener("mouseover", this.showJavaScriptLinkInfo, false);
				elm.removeEventListener("mouseout", this.hideInfo, false);
			}
			state.affectedElms = [];
		}
	};
}();